
#include <Arduino.h>
#include <TFT_eSPI.h>
#include <Ticker.h>
#include <WiFi.h>
#include "PubSubClient.h" ////A client library for MQTT messaging.
#include "DHT.h"
#include <ArduinoJson.h>
#include <freertos/FreeRTOS.h>
#include <NTPClient.h>//时间服务提供程序
#include <Myword.h>//中文字符库，需要使用汉字取模软件PCtoLCD2002.exe

TFT_eSPI tft = TFT_eSPI(); 

WiFiClient espClient;
PubSubClient client(espClient);
WiFiUDP ntpUDP;

NTPClient timeClient(ntpUDP,"ntp.aliyun.com");//时间服务器地址
const char *host = "api.seniverse.com";//心知天气服务器地址
String now_address="",now_temperature="",now_weather="",now_weather_code="";


void showMyFont(int32_t x, int32_t y, const char c[3], uint32_t color) { 
    for (int k = 0; k <= 57; k++)// 根据字库的字数调节循环的次数
    if (hanzi[k].Index[0] == c[0] && hanzi[k].Index[1] == c[1] && hanzi[k].Index[2] == c[2])
    { 
        tft.drawBitmap(x, y, hanzi[k].hz_Id, hanzi[k].hz_width, 16, color);
    }
}
  /*******************整句汉字显示****************/
void showMyFonts(int32_t x, int32_t y, const char str[], uint32_t color) { 
    //显示整句汉字，字库比较简单，上下、左右输出是在函数内实现
    int x0 = x;
    for (int i = 0; i < strlen(str); i += 3) {
      showMyFont(x0, y, str+i, color);
      x0 += 17;
    }
}


void Display_Time() {

  timeClient.update();
  unsigned long epochTime = timeClient.getEpochTime();
  //打印时间
  int currentSec = timeClient.getSeconds();
  int currentMinute = timeClient.getMinutes();
  int currentHour = timeClient.getHours();
  int weekDay = timeClient.getDay();
  //将epochTime换算成年月日
  struct tm *ptm = gmtime ((time_t *)&epochTime);
  int monthDay = ptm->tm_mday;
  int currentMonth = ptm->tm_mon+1;
  int currentYear = ptm->tm_year+1900;


  //tft.fillRect(0,0,128,60,TFT_BLACK);  //上部分清屏
  tft.fillRect(102,42,32,16,TFT_BLACK);     //部分区域清屏，刷新秒

  //10+2+10=22，“数字”分辨率10*14像素，连续显示时间隔2像素
  tft.setCursor(102, 42, 1);                //设置文本起始坐标
  tft.setTextColor(TFT_RED);                //设置文本颜色为白色
  tft.setTextSize(2);                       //设置文字的大小 (1~7)
  if (currentSec < 10){                     //将 0-9 变为00-09
    tft.println(0);                    
    tft.setCursor(114, 42, 1);              
    tft.setTextColor(TFT_RED);              
    tft.setTextSize(2);                      
    tft.println(currentSec);                     
  }
  else{
    tft.println(currentSec);               //显示文字秒
  }  


  if (currentSec==0){                       //刷新分
    tft.fillRect(55,28,44,37,TFT_BLACK);    //20+4+20=44 
  }
  delay(50);
  tft.setCursor(55, 28, 1);                
  //tft.setTextFont(7);
  tft.setTextColor(TFT_CYAN);             
  tft.setTextSize(4);                     
  if (currentMinute < 10) {
    tft.println(0);                       
    tft.setCursor(79, 28, 1);               
    tft.setTextColor(TFT_CYAN);              
    tft.setTextSize(4);                     
    tft.println(currentMinute);               
  }
  else{
    tft.println(currentMinute);                
  }


  if (currentMinute==0 && currentSec==0){    //刷新时
    tft.fillRect(1,28,44,37,TFT_BLACK); 
  }
  delay(50);
  tft.setCursor(1, 28, 1);            
  //tft.setTextFont(7);
  tft.setTextColor(TFT_CYAN);         
  tft.setTextSize(4);                
  if (currentHour < 10) {
    //tft.println(0);
    tft.setCursor(25, 28, 1);   
    tft.setTextColor(TFT_CYAN);     
    tft.setTextSize(4);                      
    tft.println(currentHour);        
  }
  else{
    tft.println(currentHour);        
  }

  tft.setCursor(40, 28, 1);                //时分分隔符
  tft.setTextColor(TFT_CYAN);       
  tft.setTextSize(4);                
  tft.println(":");    

    if (currentHour==0 && currentMinute==0 && currentSec==0){      //刷新 日、周
    tft.fillRect(102,5,22,14,TFT_BLACK); 
    tft.fillRect(5,5,32,16,TFT_BLACK); 
  }
    switch(weekDay){
    case 0: showMyFonts(5, 5, "周日", TFT_GREENYELLOW);break; 
    case 1: showMyFonts(5, 5, "周一", TFT_GREENYELLOW);break; 
    case 2: showMyFonts(5, 5, "周二", TFT_GREENYELLOW);break; 
    case 3: showMyFonts(5, 5, "周三", TFT_GREENYELLOW);break; 
    case 4: showMyFonts(5, 5, "周四", TFT_GREENYELLOW);break; 
    case 5: showMyFonts(5, 5, "周五", TFT_GREENYELLOW);break; 
    case 6: showMyFonts(5, 5, "周六", TFT_GREENYELLOW);break; 
    default: break;
  }
  
  tft.setCursor(102, 5, 1);                
  tft.setTextColor(TFT_YELLOW);          
  tft.setTextSize(2);                   
  tft.println(monthDay);    
 
  tft.drawLine(0,23, 128, 23, TFT_WHITE);  //画线 

  if (monthDay==1 && currentHour==0 && currentMinute==0 && currentSec==0){   //刷新月
    tft.fillRect(65,5,22,14,TFT_BLACK); 
  }
  tft.setCursor(77, 5, 1);               
  tft.setTextColor(TFT_YELLOW);          
  tft.setTextSize(2);                    
  tft.println(currentMonth);


  tft.setCursor(89, 5, 1);                 //月日分隔符
  tft.setTextColor(TFT_WHITE);             
  tft.setTextSize(2);                     
  tft.println("/");  
  
  if (currentMonth==1 && monthDay==1 && currentHour==0 && currentMinute==0 && currentSec==0){  //刷新年
    tft.fillRect(102,28,23,7,TFT_BLACK); 
  }
  tft.setCursor(102, 28, 1);             
  tft.setTextColor(TFT_RED);          
  tft.setTextSize(1);                       
  tft.println(currentYear);  
}

void Display_Weather() {
  //创建TCP连接
  WiFiClient client;

  const int httpPort = 80;
  if (!client.connect(host, httpPort))
  {
    Serial.println("connection failed");  //网络请求无响应打印连接失败
    return;
  }
  
  //https://api.seniverse.com/v3/weather/now.json?key=Sn6mHF-q9M_Am4ukC&location=putian&language=zh-Hans&unit=c
  //URL请求地址 //改为你的api密钥和城市拼音 
  String url ="/v3/weather/now.json?key=Sn6mHF-q9M_Am4ukC&location=putian&language=zh-Hans&unit=c";
  //发送网络请求
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
            "Host: " + host + "\r\n" +
            "Connection: close\r\n\r\n");
  for(int i = 0; i < 5; i++) {
    Display_Time();//利用等待 天气服务器响应的时间 更新时间信息
    delay(1000);   //间隔1秒访问ntp,刷新时间戳
  }

  //定义answer变量用来存放请求网络服务器后返回的数据
  String answer;
  while(client.available())
  {
    String line = client.readStringUntil('\r');
    answer += line;
  }
  //断开服务器连接
  client.stop();

  //获得json格式的数据
  String jsonAnswer;
  int jsonIndex;
  //找到有用的返回数据位置i 返回头不要
  for (int i = 0; i < answer.length(); i++) {
    if (answer[i] == '{') {
      jsonIndex = i;
      break;
    }
  }
  jsonAnswer = answer.substring(jsonIndex);

  //解析获取到的json数据
  //https://arduinojson.org/v7/assistant/ 进入网站转换代码
  StaticJsonDocument<512> doc;
  DeserializationError error = deserializeJson(doc, jsonAnswer);


  JsonObject results_0 = doc["results"][0];
  JsonObject results_0_location = results_0["location"];
  const char* results_0_location_id = results_0_location["id"]; // "WW0CWDZP17BC"
  const char* results_0_location_name = results_0_location["name"]; // "泉州"

  JsonObject results_0_now = results_0["now"];
  const char* results_0_now_text = results_0_now["text"]; // "阴"
  const char* results_0_now_code = results_0_now["code"]; // "9"
  const char* results_0_now_temperature = results_0_now["temperature"]; // "3"

  const char* results_0_last_update = results_0["last_update"]; // "2022-01-29T17:25:01+08:00"

  now_address = results_0_location_name;
  now_weather = results_0_now_text;
  now_weather_code = results_0_now_code;
  now_temperature = results_0_now_temperature;

  tft.fillRect(5,70,32,16,TFT_BLACK);       //打印地区
  if(now_address=="莆田") {
    showMyFonts(5,70,"莆田" , TFT_GOLD);
  }
  
  #define X  95
  #define Y  70
  tft.fillRect(X,Y,32,16,TFT_BLACK);
  switch (std::atoi(now_weather_code.c_str())) {//天气代码不是int类型，要先转换
  /************************************************************************************
  天气代码是由心知天气的API接口提供的，详见[天气现象代码说明]
  (https://seniverse.yuque.com/books/share/e52aa43f-8fe9-4ffa-860d-96c0f3cf1c49/yev2c3)
  *************************************************************************************/
     case 0: showMyFonts(X,Y,"晴" , TFT_GREEN); break;
     case 1: showMyFonts(5,140,"夜晚晴" , TFT_GREEN); break;
     case 4: showMyFonts(X,Y,"多云" , TFT_GREEN); break;
     case 5: showMyFonts(5,140,"晴间多云" , TFT_GREEN); break;
     case 7: showMyFonts(5,140,"大部多云" , TFT_GREEN); break;
     case 9: showMyFonts(X,Y,"阴" , TFT_GREEN); break;
     case 10: showMyFonts(X,Y,"阵雨" , TFT_GREEN); break;
     case 13: showMyFonts(X,Y,"小雨" , TFT_GREEN); break;
     case 14: showMyFonts(X,Y,"中雨" , TFT_GREEN); break;
     case 15: showMyFonts(X,Y,"大雨" , TFT_GREEN); break;
     case 16: showMyFonts(X,Y,"暴雨" , TFT_GREEN); break;
     case 32: showMyFonts(X,Y,"风" , TFT_GREEN); break;
     case 37: showMyFonts(X,Y,"冷" , TFT_GREEN); break;
     case 38: showMyFonts(X,Y,"热" , TFT_GREEN); break;
     case 99: showMyFonts(X,Y,"未知" , TFT_GREEN); break;
    default: break;
  }
      
  tft.fillRect(50,70,36,20,TFT_BLACK); 
  tft.setCursor(50, 70, 1);                 
  tft.setTextColor(TFT_SKYBLUE);             
  tft.setTextSize(2);                    
  tft.println(now_temperature);               
  showMyFonts(75,70,"℃",TFT_SKYBLUE); 
}